package com.xls.aclservice.service.impl;

import com.mysql.cj.util.StringUtils;
import com.xls.aclservice.entity.SysMenu;
import com.xls.aclservice.entity.SysRole;
import com.xls.aclservice.entity.SysUser;
import com.xls.aclservice.entity.SysUserRole;
import com.xls.aclservice.vo.SignupVo;
import com.xls.base.mapper.StudentMapper;
import com.xls.aclservice.mapper.SysUserRoleMapper;
import com.xls.base.model.*;
import com.xls.aclservice.mapper.SysMenuMapper;
import com.xls.aclservice.mapper.SysUserMapper;
import com.xls.aclservice.service.SysMenuService;
import com.xls.aclservice.service.SysUserService;
import com.xls.aclservice.vo.UserInfo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xls.base.exception.BusinessException;
import com.xls.commonutils.FormUtils;
import com.xls.commonutils.JwtUtils;
import com.xls.commonutils.RandomUtils;
import com.xls.commonutils.RedisUtil;
import com.xls.entity.SecurityUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Service
public class LoginServiceImpl {

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysMenuService sysMenuService;

    @Autowired
    private SysMenuMapper sysMenuMapper;

    @Autowired
    private StudentMapper studentMapper;

    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private RedisUtil redisUtil;

    //@Autowired
    //private RedisTemplate<String, Serializable> redisTemplate;

    @Autowired
    private RedisTemplate redisTemplate;

    public String login(String username, String password) {
        SysUser sysUser = sysUserMapper.selectOne(new QueryWrapper<SysUser>().eq("username", username));
        if (sysUser == null) {
            throw new BusinessException(777, "用户名不正确");
        } else if (!sysUser.getStatus()) {
            throw new BusinessException(777, "用户被禁用");
        } else if (!passwordEncoder.matches(password, sysUser.getPassword())) {
            throw new BusinessException(777, "密码不正确");
        }
        List<SysMenu> sysMenus = sysMenuMapper.getMenusById(sysUser.getId());
        List<String> permissionValueList = sysMenus.stream().map(SysMenu::getPermissionValue).collect(Collectors.toList());

        String token = jwtUtils.generateToken(sysUser.getUsername());
        // 登陆时将用户的权限集合存储到redis中
        redisTemplate.opsForValue().set(username, permissionValueList);
        return token;
    }

    public UserInfo info() {
        SecurityUser securityUser = (SecurityUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        UserInfo userInfo = new UserInfo();
        userInfo.setName(securityUser.getUsername());
        SysUser sysUser1 = sysUserService.selectByUsername(securityUser.getUsername());
        // 改造了security,变成公共模块,user的其他信息只能通过username来查询,或者在token里面携带其他信息
        // 然后注入到security的user中
        userInfo.setAvatar(sysUser1.getAvatar());
        SysUser sysUser = sysUserMapper.getUser(sysUser1.getId());
        if (sysUser == null) {
            throw new BusinessException(7777, "用户角色被禁用");
        }
        List<String> roles = sysUser.getSysRoles().stream().map(SysRole::getDescription).collect(Collectors.toList());
        userInfo.setRoles(roles);
        return userInfo;
    }

    public List<SysMenu> getMenu() {
        SecurityUser securityUser = (SecurityUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        return sysMenuService.getMenus(sysUserService.selectByUsername(securityUser.getUsername()).getId());
    }

    public void logout() {
        // 注销时将用户的权限集合从redis中删除
        SecurityUser securityUser = (SecurityUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        redisTemplate.delete(securityUser.getUsername());
    }

    /**
     * 获取验证码
     *
     * @return
     */
    @Transactional
    public String getCode(String phone) {
        Integer count = sysUserMapper.selectCount(new QueryWrapper<SysUser>().eq("phone", phone));
        if (count != 0) {
            throw new BusinessException(7777, "该手机号已被注册");
        }
        if (StringUtils.isEmptyOrWhitespaceOnly(phone)) {
            throw new BusinessException(7777, "手机号不能为空");
        }
        if (!FormUtils.isMobile(phone)) {
            throw new BusinessException(7777, "请输入正确的手机号");
        }
        //生成验证码
        String sixBitRandom = RandomUtils.getSixBitRandom();
        //保存到redis中,并且设置过期时间60s
        redisUtil.set(phone, sixBitRandom, 60);
        return sixBitRandom;
    }

    /**
     * 学生注册
     *
     * @param signupVo
     */
    @Transactional
    public void signup(SignupVo signupVo) {
        Student student = studentMapper.selectOne(new QueryWrapper<Student>().eq("sno", signupVo.getSno()));
        if (student == null) {
            throw new BusinessException(7777, "请检查学号");
        }
        if (!student.getPhone().equals(signupVo.getPhone())) {
            throw new BusinessException(7777, "请检查手机号");
        }
        String code = (String) redisUtil.get(signupVo.getPhone());
        if (code == null) {
            throw new BusinessException(7777, "验证码已过期");
        } else if (!code.equals(signupVo.getCode())){
            throw new BusinessException(7777, "验证码不正确");
        }
        SysUser sysUser = new SysUser();
        sysUser.setUsername(signupVo.getSno());
        sysUser.setPassword(passwordEncoder.encode(signupVo.getPassword()));
        sysUser.setName(student.getName());
        sysUser.setGender(student.getGender());
        sysUser.setPhone(signupVo.getPhone());
        sysUser.setAvatar("http://121.43.155.238:9000/dormitory/defaultavatar"+ student.getGender() +".png");
        sysUser.setStatus(true);
        sysUserMapper.insert(sysUser);
        SysUserRole sysUserRole = new SysUserRole();
        sysUserRole.setUserId(sysUser.getId());
        sysUserRole.setRoleId(2L);
        sysUserRoleMapper.insert(sysUserRole);
    }
}
